package com.qiqv.demo;

import com.qiqv.agentDemo.Apple;
import com.qiqv.demo.transformer.AppleTransformer;
import com.qiqv.demo.transformer.LogTransformer;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;

/**
 * @author hjr
 * @version 1.0
 * @date 2023/12/9 13:53
 */
public class JavaAgentTest {

    /**
     * 方式一：使用 addTransformer 来实现类文件代理
     * @param agentArgs
     * @param inst
     */
/*    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("premain start");
        System.out.println("args:"+agentArgs);
        inst.addTransformer(new OrderTransformer());
    }*/

/*    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new AppleTransformer());
    }*/

    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new LogTransformer());
    }

    public static void agentmain(String agentArgs, Instrumentation instrumentation) {
        System.out.println("agent main start");
        System.out.println("args:"+agentArgs);
    }

    /**
     * 方式二：使用 redefineClassed方法
     *      这个和方式一其实差不多，只是方式一是通过手动指定类的全路径来加载被代理的类，而方式二是通过 xxx.class的方式来获取要被代理的类
     *      但个人觉得这种方式要麻烦一些，因为还要手动引入相关的对象进来，如果agent和被代理的对象不在同一个项目中，那么处理起来要麻烦的多
     * @param agentArgs
     * @param inst
     * @throws UnmodifiableClassException
     * @throws ClassNotFoundException
     */
/*    public static void premain(String agentArgs, Instrumentation inst) throws UnmodifiableClassException, ClassNotFoundException {
        System.out.println("premain start");
        System.out.println("args:"+agentArgs);
        String fileName="C:\\Users\\98093\\Desktop\\class\\Apple.class";
        ClassDefinition def=new ClassDefinition(Apple.class,getNewClassBytes(fileName));
        inst.redefineClasses(new ClassDefinition[]{def});
    }*/

    private static byte[] getNewClassBytes(String fileName) {
        File file = new File(fileName);
        try(InputStream is = new FileInputStream(file);
            ByteArrayOutputStream bs = new ByteArrayOutputStream()){
            long length = file.length();
            byte[] bytes = new byte[(int) length];

            int n;
            while ((n = is.read(bytes)) != -1) {
                bs.write(bytes, 0, n);
            }
            return bytes;
        }catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

/*    public static void premain(String agentArgs, Instrumentation inst) throws UnmodifiableClassException, ClassNotFoundException {
        System.out.println("premain start");
        System.out.println("args:"+agentArgs);
        inst.addTransformer(new LogTransformer());
    }*/

    public static void main(String[] args) {
    }


}
